package com.example.thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadDeadlock {

    public static void main(String[] args) throws InterruptedException {
        Object obj1 = new Object();
        Object obj2 = new Object();
        Object obj3 = new Object();

        Lock lock1 = new ReentrantLock();
        Lock lock2 = new ReentrantLock();
        Thread t1 = new Thread(new SyncThread1(lock1, lock2), "t1");
        Thread t2 = new Thread(new SyncThread1(lock2, lock1), "t2");
        //Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3");

        t1.start();
        //Thread.sleep(1000);
        t2.start();
        //Thread.sleep(5000);
        //t3.start();

    }

}

class SyncThread implements Runnable{
    private Object obj1;
    private Object obj2;

    public SyncThread(Object o1, Object o2){
        this.obj1=o1;
        this.obj2=o2;
    }
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name + " 11 acquiring lock on "+obj1);
        synchronized (obj1) {
            System.out.println(name + " 11 acquired lock on "+obj1);
            work();
            System.out.println(name + " 22 acquiring lock on "+obj2);
            synchronized (obj2) {
                System.out.println(name + " 22 acquired lock on "+obj2);
                work();
            }
            System.out.println(name + " 22  released lock on "+obj2);
        }
        System.out.println(name + "  11 released lock on "+obj1);
        System.out.println(name + " finished execution.");
    }
    private void work() {
//        try {
//            Thread.sleep(30000);
//            wait();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
    }
}

class SyncThread1 implements Runnable{
    private Lock lock1;
    private Lock lock2;

    public SyncThread1(Lock o1, Lock o2){
        this.lock1=o1;
        this.lock2=o2;
    }
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name + " 11 acquiring lock on "+lock1);

        lock1.lock();
        {
            System.out.println(name + " 11 acquired lock on "+lock1);

            System.out.println(name + " 22 acquiring lock on "+lock2);
            lock2.lock();

                System.out.println(name + " 22 acquired lock on "+lock2);
        }
    }
    private void work() {
//        try {
//            Thread.sleep(30000);
//            wait();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
    }
}